package cn.lg.soar.general.s3;

import cn.lg.soar.common.util.FileTypeUtils;
import cn.lg.soar.general.entity.FileStorage;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.*;
import lombok.SneakyThrows;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

/**
 * @author luguoxiang 469599794@qq.com
 * @Date: 2024/3/1 17:25
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class AmazonS3FileTemplateImpl implements FileTemplate {

    private final AmazonS3 amazonS3;
    private final int configVersion;

    public AmazonS3FileTemplateImpl(FileStorage storage) {
        this.configVersion = storage.getVersion();
        String endpoint = storage.getEndpoint();
        String accessKey = storage.getAccessKey();
        String secretKey = storage.getSecretKey();
        // url以及region配置
        AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
                endpoint,
                null
        );
        ClientConfiguration clientConfig = new ClientConfiguration();
        clientConfig.setProtocol(Protocol.HTTPS);

        AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
        AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);

        // 创建S3客户端
        amazonS3 = AmazonS3Client.builder()
                .withEndpointConfiguration(endpointConfiguration)
                .withClientConfiguration(clientConfig)
                .withCredentials(awsCredentialsProvider)
                .disableChunkedEncoding()
                .withPathStyleAccessEnabled(storage.getPathStyleAccess())
                .withForceGlobalBucketAccessEnabled(true)
                .build();
    }

    @Override
    @SneakyThrows
    public void createBucket(String bucketName) {
        if ( !amazonS3.doesBucketExistV2(bucketName) ) {
            amazonS3.createBucket(bucketName);
        }
    }

    @Override
    @SneakyThrows
    public List<Bucket> listBuckets() {
        return amazonS3.listBuckets();
    }

    @Override
    @SneakyThrows
    public void removeBucket(String bucketName) {
        amazonS3.deleteBucket(bucketName);
    }

    @Override
    public void upload(String bucketName, String filename, InputStream stream) {
        try {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(stream.available());
            objectMetadata.setContentType(FileTypeUtils.getContentType(filename));
            amazonS3.putObject(bucketName, filename, stream, objectMetadata);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    @SneakyThrows
    public String getUrl(String bucketName, String objectName, Integer expires) {
        Date date = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, expires);
        return amazonS3.generatePresignedUrl(bucketName, objectName, calendar.getTime())
                .toString();
    }

    @Override
    public String getUrl(String bucketName, String filename) {
        return amazonS3.getUrl(bucketName, filename).toString();
    }

    @Override
    @SneakyThrows
    public void removeFile(String bucketName, String objectName) {
        amazonS3.deleteObject(bucketName, objectName);
    }

    @Override
    @SneakyThrows
    public S3Object getObject(String bucketName, String objectName) {
        return amazonS3.getObject(bucketName, objectName);
    }

    @Override
    @SneakyThrows
    public List<S3ObjectSummary> listObjects(String bucketName, String prefix, boolean recursive) {
        ObjectListing objectListing = amazonS3.listObjects(bucketName, prefix);
        return objectListing.getObjectSummaries();
    }

    @Override
    public boolean isExist(String bucketName, String filename) {
        return amazonS3.doesObjectExist(bucketName, filename);
    }

    @Override
    public int getConfigVersion() {
        return configVersion;
    }

    @Override
    public void test() {
        amazonS3.listBuckets();
    }

    @Override
    public void disconnect() {
        // TODO 关闭连接
    }
}